# UMD 插件

import { SourceCode } from 'rspress/theme';

<SourceCode href="https://github.com/web-infra-dev/rsbuild/tree/main/packages/plugin-umd" />

用于构建 UMD 格式的产物。

:::tip 什么是 UMD
UMD 是 Universal Module Definition 的缩写，它是同时兼容 AMD、CommonJS 和全局变量定义方式的模块规范。UMD 产物指的是遵循 UMD 规范的模块，它能够在多种环境中被加载和使用，包括浏览器环境和 Node.js 环境。
:::

## 快速开始

### 安装插件

你可以通过如下的命令安装插件:

import { PackageManagerTabs } from '@theme';

<PackageManagerTabs command="add @rsbuild/plugin-umd -D" />

### 注册插件

你可以在 `rsbuild.config.ts` 文件中注册插件：

```ts title="rsbuild.config.ts"
import { pluginUmd } from '@rsbuild/plugin-umd';

export default {
  plugins: [pluginUmd({ name: 'myLib' })],
};
```

## 示例

比如项目中有以下代码：

```js title="src/index.js"
export function double(a) {
  return a * 2;
}
```

在使用 UMD 插件时，Rsbuild 构建会生成 UMD 格式的 `dist/index.js` 文件。

- 在浏览器中加载该文件时，可以通过 window 上的全局变量访问其中导出的内容，比如：

```js
console.log(window.myLib.double(1)); // -> 2
```

- 在 Node.js 中加载时，可以直接通过 `require` 导入，比如：

```js
const { double } = require('./dist/index.js');

console.log(double(1)); // -> 2
```

## 选项

### name

`name` 为必填字段，用于指定 UMD library 的名称，对应 Rspack 的 [output.library.name](https://rspack.dev/config/output#outputlibraryname) 选项。

- **类型：** `string`
- **示例：**

```js
pluginUmd({
  name: 'foo', // 通过 window.foo 访问
});
```

### export

指定将哪一个导出作为 UMD library 的内容。在默认情况下，`export` 是 undefined，这将导出整个命名空间对象。

- **类型：** `string | string[]`
- **默认值：** `undefined`
- **示例：** 将 `export` 配置为 `default`，那么通过 `window.foo` 访问的是 `export default` 导出的内容。

```js
pluginUmd({
  name: 'foo',
  export: 'default',
});
```

- **示例二：** 你也可以将数组传递给 `output.library.export`，数组会被解析为一个访问路径。

```js
pluginUmd({
  name: 'foo',
  export: ['default', 'subModule'],
});
```

```js title="src/index.js"
export default {
  // 通过 window.foo 访问的值为 1
  subModule: 1,
};
```

## 产物名称

默认情况下，UMD 插件会构建出 `dist/index.js` 文件，你可以通过 Rsbuild 的 [output.filename](/config/output/filename) 来修改产物文件的名称。

比如输出 `dist/myLib.js` 文件：

```js
export default {
  output: {
    filename: {
      js: 'myLib.js',
    },
  },
};
```

## 在浏览器中调试

你可以运行 `rsbuild dev` 命令来在浏览器中调试 UMD 产物。

首先，创建 `src/index.html`，并添加调用代码：

```html title="src/index.html"
<!doctype html>
<html>
  <head></head>
  <body>
    <script>
      console.log(window.myLib.double(1));
    </script>
  </body>
</html>
```

然后在 `rsbuild.config.ts` 中指定 `template`：

```ts title="rsbuild.config.ts"
export default {
  plugins: [pluginUmd({ name: 'myLib' })],
  html: {
    template: './src/index.html',
  },
};
```

最后运行 `npx rsbuild dev` 即可。

## HTML 生成

在使用 UMD 插件后，执行生产构建时默认不会生成 HTML 文件，这是因为 UMD 产物通常以 library 的形式进行分发，不依赖 HTML 文件。

如果你需要生成 HTML 文件，可以将 [tools.htmlPlugin](/config/tools/html-plugin) 设置为 `true`：

```ts title="rsbuild.config.ts"
export default {
  plugins: [pluginUmd({ name: 'myLib' })],
  html: {
    template: './src/index.html',
  },
  tools: {
    htmlPlugin: true,
  },
};
```

## 代码拆分

UMD 插件覆盖了 Rsbuild 默认的 chunk 拆包规则，它会将 `performance.chunkSplit.strategy` 设置为 `all-in-one`，以输出单个 bundle 产物。这是因为 UMD 产物经常会通过 CDN 来分发，并允许通过 `<script>` 标签直接引用。

如果你需要对 UMD 产物进行拆包，可以主动配置 [performance.chunkSplit](/config/performance/chunk-split)，比如：

```js
export default {
  performance: {
    chunkSplit: {
      strategy: 'split-by-experience',
    },
  },
};
```

注意 UMD 插件不会禁用 dynamic import 引起的拆包。如果你需要禁用它，可以将 Rspack 的 [output.asyncChunks](https://rspack.dev/config/output#outputasyncchunks) 选项设置为 `false`：

```js
export default {
  tools: {
    rspack: {
      output: {
        asyncChunks: false,
      },
    },
  },
};
```
